package com.datamigration;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.bss.Entity;
import com.bss.GenericDAO;
import com.bss.model.Admission;
import com.bss.model.Attendent;
import com.bss.model.Building;
import com.bss.model.Country;
import com.bss.model.CurrentAttendent;
import com.bss.model.IdCardType;
import com.bss.model.MedicalProblem;
import com.bss.model.Patient;
import com.bss.model.Payable;
import com.bss.model.Payment;
import com.bss.model.PaymentType;
import com.bss.model.Place;
import com.bss.model.Profession;
import com.bss.model.Relationship;
import com.bss.model.Religion;
import com.bss.model.Room;
import com.bss.model.RoomBooking;
import com.bss.model.State;
import com.oldbss.beans.CheckInOut;
import com.oldbss.beans.PatientRecord;
import com.oldbss.beans.Paymentsmade;
import com.oldbss.beans.RoomAllocation;
import com.oldbss.beans.Rooms;

public class BssNew {
	private EntityManager bssNewEntityManager;
	GenericDAO<Patient> patientDao;
	private BssOld bssOld = new BssOld();
	GenericDAO<Admission> admissionDao;
	private GenericDAO<Attendent> attendentDao;
	private GenericDAO<CurrentAttendent> currentAttendentDao;
	private GenericDAO<Country> countryDao;
	private GenericDAO<State> stateDao;
	private GenericDAO<Place> placeDao;
	private GenericDAO<Religion> religionDao;
	private GenericDAO<Profession> professionDao;
	private GenericDAO<MedicalProblem> medicalProblemDao;
	private GenericDAO<Building> buildingDao;
	private GenericDAO<IdCardType> idCardTypeDao;
	private GenericDAO<Relationship> relationshipDao;
	private GenericDAO<PaymentType> paymentTypeDao;
	private GenericDAO<Room> roomDao;

	public BssNew() {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("bssPU");
		this.bssNewEntityManager = emf.createEntityManager();

		this.patientDao = new GenericDAO<Patient>(Patient.class);
		this.patientDao.setEm(this.bssNewEntityManager);
		this.admissionDao = new GenericDAO<Admission>(Admission.class);
		this.admissionDao.setEm(this.bssNewEntityManager);

		this.attendentDao = new GenericDAO<Attendent>(Attendent.class);
		this.attendentDao.setEm(this.bssNewEntityManager);
		this.currentAttendentDao = new GenericDAO<CurrentAttendent>(CurrentAttendent.class);
		this.currentAttendentDao.setEm(this.bssNewEntityManager);

		this.countryDao = new GenericDAO<Country>(Country.class);
		this.countryDao.setEm(this.bssNewEntityManager);
		this.stateDao = new GenericDAO<State>(State.class);
		this.stateDao.setEm(this.bssNewEntityManager);
		this.placeDao = new GenericDAO<Place>(Place.class);
		this.placeDao.setEm(this.bssNewEntityManager);
		this.religionDao = new GenericDAO<Religion>(Religion.class);
		this.religionDao.setEm(this.bssNewEntityManager);

		this.professionDao = new GenericDAO<Profession>(Profession.class);
		this.professionDao.setEm(this.bssNewEntityManager);

		this.medicalProblemDao = new GenericDAO<MedicalProblem>(MedicalProblem.class);
		this.medicalProblemDao.setEm(this.bssNewEntityManager);
		this.buildingDao = new GenericDAO<Building>(Building.class);
		this.buildingDao.setEm(this.bssNewEntityManager);
		this.idCardTypeDao = new GenericDAO<IdCardType>(IdCardType.class);
		this.idCardTypeDao.setEm(this.bssNewEntityManager);
		this.relationshipDao = new GenericDAO<Relationship>(Relationship.class);
		this.relationshipDao.setEm(this.bssNewEntityManager);
		this.paymentTypeDao = new GenericDAO<PaymentType>(PaymentType.class);
		this.paymentTypeDao.setEm(this.bssNewEntityManager);
		this.roomDao = new GenericDAO<Room>(Room.class);
		this.roomDao.setEm(this.bssNewEntityManager);

	}

	public EntityManager getEntityManager() {
		return this.bssNewEntityManager;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void persist(GenericDAO genericDao, Entity entity) {
		genericDao.setEm(this.getEntityManager());
		genericDao.save(entity);
	}

	public void saveRoomsAndBuildings() {

		List<Object[]> buildingInfoList = this.bssOld.findAllBuildingInfo();

		for (Object[] buildingInfo : buildingInfoList) {
			List<Rooms> oldRooms = this.bssOld.findAllRoomsByBuildingName((String) buildingInfo[0]);
			List<Room> newRooms = new ArrayList<Room>();
			Building building = new Building((String) buildingInfo[0], (Integer) buildingInfo[1] + 1, newRooms);
			for (Rooms oldRoom : oldRooms) {
				newRooms.add(new Room(oldRoom.getRoomNo(), building, oldRoom.getFloorNo(), null, oldRoom.isIsDom(), false, oldRoom
						.getRoomCharges()));
			}
			building.setRooms(newRooms);
			this.buildingDao.save(building);

		}
	}

	public void saveMedicalProblems() {
		BssOld bssOld = new BssOld();
		List<String> medicalProblems = bssOld.findAllMedicalProblems();
		for (String medicalProblemName : medicalProblems) {
			if (medicalProblemName != null) {
				MedicalProblem medicalProblem = new MedicalProblem();
				medicalProblem.setName(medicalProblemName.trim());
				this.medicalProblemDao.save(medicalProblem);
			}
		}
	}

	public void saveProfessions() {
		BssOld bssOld = new BssOld();
		List<String> professions = bssOld.findAllprofession();
		for (String professionName : professions) {
			if (professionName != null) {
				Profession profession = new Profession();
				profession.setName(professionName.trim());
				this.professionDao.save(profession);
			}
		}
	}

	public void saveIdCardTypes() {
		BssOld bssOld = new BssOld();
		Set<String> professions = new HashSet<String>(bssOld.findAllIdCardType());
		for (String idCardTypeName : professions) {
			if (idCardTypeName != null) {
				IdCardType idCardType = new IdCardType();
				idCardType.setName(idCardTypeName.trim());
				this.idCardTypeDao.save(idCardType);
			}
		}
	}

	public void saveRelationship() {
		BssOld bssOld = new BssOld();
		List<String> relationships = bssOld.findAllRelationships();
		for (String relationshipName : relationships) {
			if (relationshipName != null) {
				Relationship relationship = new Relationship();
				relationship.setName(relationshipName.trim());
				this.relationshipDao.save(relationship);
			}
		}
	}

	public void savePaymentType() {
		this.paymentTypeDao.save(new PaymentType("Admission Deposit", "Admission Deposit", 0, new Date(), true));
		this.paymentTypeDao.save(new PaymentType("Room Rent", "Room Rent", 0, new Date(), true));
	}

	public List<Profession> findAllProfessions() {
		return this.professionDao.findAll();
	}

	public Profession findProfession(List<Profession> professions, String professionName) {
		if (professionName != null) {
			for (Profession profession : professions) {
				if (profession.getName().equalsIgnoreCase(professionName.trim())) {
					return profession;
				}
			}
		}
		return null;
	}

	public IdCardType findIdCartType(List<IdCardType> idCardTypes, String idCardName) {
		for (IdCardType idCardType : idCardTypes) {
			if ((idCardName != null) && idCardType.getName().equalsIgnoreCase(idCardName.trim())) {
				return idCardType;
			}
		}
		return null;
	}

	public List<IdCardType> findAllIdCardTypes() {
		return this.idCardTypeDao.findAll();
	}

	public List<Relationship> findAllRelationships() {
		return this.relationshipDao.findAll();
	}

	public Relationship findRelationship(List<Relationship> relationships, String relationshipName) {
		for (Relationship relationship : relationships) {
			if (relationship.getName().equalsIgnoreCase(relationshipName.trim())) {
				return relationship;
			}
		}
		return null;
	}

	protected List<RoomBooking> getRoomBookings(CheckInOut checkInOut, List<RoomAllocation> oldRoomAllocations, List<Room> rooms,
			Admission admission) {
		List<RoomBooking> roomBookings = new ArrayList<RoomBooking>();
		for (RoomAllocation roomAllocation : oldRoomAllocations) {
			if (checkInOut.getTransactionId().equals(roomAllocation.getCheckInOut().getTransactionId())) {
				RoomBooking roomBooking = new RoomBooking();
				roomBooking.setAdmission(admission);
				roomBooking.setRoom(this.getNewRoom(rooms, roomAllocation.getRooms().getRoomNo()));
				roomBooking.setCheckInDate(roomAllocation.getDateofstay());
				roomBooking.setCheckOutDate(roomAllocation.getDateofcheckout());
				roomBooking.setTotalPayment(roomAllocation.getAmount());
				roomBookings.add(roomBooking);
			}
		}
		return roomBookings;
	}

	protected Room getNewRoom(List<Room> rooms, String roomNo) {
		for (Room room : rooms) {
			if (room.getRoomNumber().equalsIgnoreCase(roomNo)) {
				return room;
			}
		}
		return null;
	}

	protected Payment getAdmissionPayment(Admission admission, CheckInOut checkInOut) {
		Payment admissionPayment = new Payment();
		PaymentType paymentType = this.paymentTypeDao.findAll().get(0);

		admissionPayment.setPaymentType(paymentType);
		admissionPayment.setPayable(admission);
		admissionPayment.setDate(checkInOut.getDateOfStay());
		admissionPayment.setAmount(checkInOut.getDepositAmount());
		admissionPayment.setRefund(true);
		return admissionPayment;

	}

	protected List<Payment> getPayments(Integer transactionId, List<Paymentsmade> paymentsMade, Payable admission) {
		List<Payment> payments = new ArrayList<Payment>();
		PaymentType paymentType = this.paymentTypeDao.findAll().get(1);
		for (Paymentsmade paymentMade : paymentsMade) {
			if (paymentMade.getCheckInOut().getTransactionId().equals(transactionId)) {
				Payment payment = new Payment();
				payment.setPaymentType(paymentType);
				payment.setPayable(admission);
				payment.setDate(paymentMade.getDate());
				payment.setDateEnd(paymentMade.getPaymentupto());
				payment.setDateStart(paymentMade.getPaymentfrom());
				payment.setAmount(paymentMade.getAmount());
				payment.setRefund(false);
				payments.add(payment);
			}

		}
		return payments;
	}

	public Patient savePatient(List<Patient> patients, PatientRecord patientRecord, List<IdCardType> idCardTypes,
			List<Profession> professions, Place place, Religion religion) {
		Patient patient = this.getExistingPatient(patients, patientRecord);
		if (patient == null) {
			IdCardType idCardType = this.findIdCartType(idCardTypes, patientRecord.getIdCardType());
			Profession profession = this.findProfession(professions, patientRecord.getProfession());
			patient = new Patient(patientRecord.getPatientId(), idCardType, profession, patientRecord.getPatientFirstName(),
					patientRecord.getPatientMiddleName(), patientRecord.getPatientLastName(), patientRecord.getSex().toUpperCase(),
					patientRecord.getAddress(), patientRecord.getContactNo(), patientRecord.getIdCardNumber(),
					patientRecord.getPhotograph(), place, religion);
			this.savePatient(patient);
			patients.add(patient);
		}
		return patient;

	}

	public Patient getExistingPatient(List<Patient> patients, PatientRecord patientRecord) {
		for (Patient patient : patients) {
			if (patient.getPhone().equalsIgnoreCase(patientRecord.getContactNo())) {
				return patient;
			}
		}
		return null;
	}

	public List<MedicalProblem> findAllMedicalProblems() {
		List<MedicalProblem> medicalProblems = this.medicalProblemDao.findAll();
		return medicalProblems;
	}

	public MedicalProblem findMedicalProblem(List<MedicalProblem> medicalProblems, String medicalProblemName) {
		for (MedicalProblem medicalProblem : medicalProblems) {
			if ((medicalProblemName != null) && medicalProblem.getName().equalsIgnoreCase(medicalProblemName.trim())) {
				return medicalProblem;
			}
		}
		return null;
	}

	protected List<Room> findAllRooms() {
		List<Room> rooms = this.roomDao.findAll();
		return rooms;
	}

	public void savePatient(Patient patient) {
		this.patientDao.save(patient);
	}

	public void saveAdmission(Admission admission) {
		if (admission != null) {
			this.admissionDao.save(admission);
		}
	}

	public void saveAttendents(Set<Attendent> attendents) {
		for (Attendent attendent : attendents) {
			this.attendentDao.save(attendent);
		}
	}

	public void saveCurrentAttendants(List<CurrentAttendent> currentAttendents) {
		for (CurrentAttendent currentAttendent : currentAttendents) {
			this.currentAttendentDao.save(currentAttendent);
		}
	}

	public void saveReligion() {
		this.religionDao.save(new Religion("Hindu"));
	}

	public void savePlace() {
		Country country = new Country("India");
		State state = new State("Bihar", country);
		Place place = new Place("Patna", state);
		this.placeDao.save(place);
	}

	public Religion getReligion() {
		return this.religionDao.findAll().get(0);
	}

	public Place getPlace() {
		return this.placeDao.findAll().get(0);
	}

}
